﻿using System;
using System.Collections.Generic;
using FakeItEasy;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities.Governance;
using Sustainalytics.Governance.BusinessLogic.PdfMetadata;
using Xunit;

namespace Sustainalytics.Governance.BusinessLogic.Tests
{
    public class GovernancePdfMetadataManagerTest
    {
        private readonly IGovernancePdfProfileMetadataRepository _governancePdfProfileMetadataRepository;
        private readonly IRepositoryCollection<GovernanceInsightInputFile> _fileRepository;
        private GovernancePdfMetadataManager _target;

        public GovernancePdfMetadataManagerTest()
        {
            _governancePdfProfileMetadataRepository = A.Fake<IGovernancePdfProfileMetadataRepository>();
            _fileRepository = A.Fake<IRepositoryCollection<GovernanceInsightInputFile>>();
            _target = new GovernancePdfMetadataManager(_governancePdfProfileMetadataRepository,_fileRepository, "");
        }

        /// <summary>
        /// A <see cref="GovernancePdfMetadataManager.UpdateGovernancePdfProfileMetadata(GovernancePdfProfileMetadataDto, string)"/>
        /// </summary>
        public class UpdateGovernancePdfProfileMetadata_Should : GovernancePdfMetadataManagerTest
        {
            [Fact]
            public void CreatePdfProfileIfProfileDoesNotExists()
            {
                var governancePdfProfileMetadataDto = new GovernancePdfProfileMetadataDto()
                {
                    CompanyId = Guid.NewGuid().ToString(),
                    FileId = Guid.NewGuid().ToString()
                };
                A.CallTo(() => _governancePdfProfileMetadataRepository.GetFileMetadata(A<Guid>.Ignored, A<GovernancePdfType>.Ignored)).ReturnsLazily(() => null);

                A.CallTo(() => _governancePdfProfileMetadataRepository.CreateOrUpdate(A<GovernancePdfProfileMetadata>.Ignored)).Returns(true);

                var result = _target.UpdateGovernancePdfProfileMetadata(governancePdfProfileMetadataDto, "ionut.pintea@sustainalytics.com");
                A.CallTo(() => _governancePdfProfileMetadataRepository.CreateOrUpdate(A<GovernancePdfProfileMetadata>.Ignored)).MustHaveHappened();
                Assert.NotNull(result);
            }

            [Fact]
            public void UpdatePdfProfileIfProfileDoesNotExists()
            {
                var governancePdfProfileMetadataDto = new GovernancePdfProfileMetadataDto()
                {
                    CompanyId = Guid.NewGuid().ToString(),
                    FileId = Guid.NewGuid().ToString()
                };

                var pdfProfileMetadata = new GovernancePdfProfileMetadata()
                {
                    CompanyId = Guid.NewGuid(),
                    FileId = Guid.NewGuid()
                };
                A.CallTo(() => _governancePdfProfileMetadataRepository.GetFileMetadata(A<Guid>.Ignored, A<GovernancePdfType>.Ignored)).ReturnsLazily(() => pdfProfileMetadata);

                A.CallTo(() => _governancePdfProfileMetadataRepository.CreateOrUpdate(A<GovernancePdfProfileMetadata>.Ignored)).Returns(true);

                var result = _target.UpdateGovernancePdfProfileMetadata(governancePdfProfileMetadataDto, "ionut.pintea@sustainalytics.com");
                A.CallTo(() => _governancePdfProfileMetadataRepository.CreateOrUpdate(A<GovernancePdfProfileMetadata>.Ignored)).MustHaveHappened();
                Assert.NotNull(result);
            }
        }

        /// <summary>
        /// A <see cref="GovernancePdfMetadataManager.GetProfileByCompany(Guid, string)"/>
        /// </summary>
        public class GetProfileByCompany_Should : GovernancePdfMetadataManagerTest
        {
            [Fact]
            public void ReturnEmptyListWhenCompanyIdDoesNotExists()
            {
                var returned = _target.GetProfileByCompany(Guid.NewGuid(), "");
                Assert.Empty(returned);
            }

            [Fact]
            public void ReturnProfilesWhenCompanyIdExists()
            {
                var returnedList = new List<GovernancePdfProfileMetadata>();
                for (int i = 0; i < 1; i++)
                {
                    returnedList.Add(new GovernancePdfProfileMetadata()
                    {
                        FileId = Guid.NewGuid(),
                        Id = Guid.NewGuid(),
                        CompanyId = Guid.NewGuid(),
                    });
                }

                returnedList.Add(new GovernancePdfProfileMetadata());
                A.CallTo(() => _governancePdfProfileMetadataRepository.ReadByCompanyId(A<Guid>.Ignored)).ReturnsLazily(() => returnedList);

                var returned = _target.GetProfileByCompany(Guid.NewGuid(), "http://localhost:10280/");
                Assert.Equal(returned.Count, 2);
            }
        }
        /// <summary>
        /// A <see cref="GovernancePdfMetadataManager.DeletePdfMetadataFile(Guid)"/>
        /// </summary>
        public class DeletePdfMetadataFile_Should : GovernancePdfMetadataManagerTest
        {
            [Fact]
            public void ThrowNotFoundExceptionWhenFileIdIsNull()
            {
                Assert.Throws<ArgumentNullException>(() => _target.DeletePdfMetadataFile(Guid.Empty));
            }
            [Fact]
            public void CallPdfProfileMetadataRepositoryWhenFileIdIsNotNull()
            {
                A.CallTo(() => _governancePdfProfileMetadataRepository.GetFileMetadata(A<Guid>.Ignored)).Returns(new GovernancePdfProfileMetadata());
                A.CallTo(() => _governancePdfProfileMetadataRepository.CreateOrUpdate(A<GovernancePdfProfileMetadata>.Ignored)).Returns(false);

                _target.DeletePdfMetadataFile(Guid.NewGuid());

                A.CallTo(() => _governancePdfProfileMetadataRepository.CreateOrUpdate(A<GovernancePdfProfileMetadata>.Ignored)).MustHaveHappened();
            }
        }
    }
}
